001 /*
002 * Copyright 2006 Stephen J. McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.metro.builder;
020
021 import java.io.IOException;
022 import java.io.OutputStream;
023 import java.io.OutputStreamWriter;
024 import java.io.Writer;
025
026 import javax.xml.XMLConstants;
027
028 import net.dpml.metro.info.Type;
029 import net.dpml.metro.info.InfoDescriptor;
030 import net.dpml.metro.info.ContextDescriptor;
031 import net.dpml.metro.info.CategoryDescriptor;
032 import net.dpml.metro.info.ServiceDescriptor;
033 import net.dpml.metro.info.EntryDescriptor;
034 import net.dpml.metro.info.Descriptor;
035
036 import net.dpml.state.State;
037 import net.dpml.state.StateEncoder;
038
039 /**
040 * Type builder.
041 *
042 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
043 * @version 1.0.1
044 */
045 public class ComponentTypeEncoder
046 {
047 private static final String XML_HEADER =
048 "<?xml version=\"1.0\"?>";
049
050 private static final String PART_SCHEMA_URN = "link:xsd:dpml/lang/dpml-part#1.0";
051 private static final String TYPE_SCHEMA_URN = "link:xsd:dpml/lang/dpml-type#1.0";
052 private static final StateEncoder STATE_GRAPH_ENCODER = new StateEncoder();
053
054 private static final String HEADER =
055 "<type xmlns=\""
056 + TYPE_SCHEMA_URN
057 + "\""
058 + "\n xmlns:xsi=\""
059 + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
060 + "\"\n xmlns:part=\""
061 + PART_SCHEMA_URN
062 + "\"\n xmlns:type=\""
063 + TYPE_SCHEMA_URN
064 + "\">";
065
066 private static final String FOOTER = "</type>";
067
068 /**
069 * Write the supplied type to an output stream.
070 * @param type the type descriptor
071 * @param output the output stream
072 * @exception IOException if an IO error occurs
073 */
074 public void export( Type type, OutputStream output ) throws IOException
075 {
076 final Writer writer = new OutputStreamWriter( output );
077 writer.write( XML_HEADER );
078 writer.write( "\n\n" );
079 writer.write( HEADER );
080 writer.write( "\n" );
081 writeBody( writer, type, " " );
082 writer.write( "\n" );
083 writer.write( FOOTER );
084 writer.write( "\n" );
085 writer.flush();
086 output.close();
087 }
088
089 private void writeBody( Writer writer, Type type, String pad ) throws IOException
090 {
091 writeTypeInfo( writer, type.getInfo(), pad );
092 writeTypeServices( writer, type.getServiceDescriptors(), pad );
093 writeTypeContext( writer, type.getContextDescriptor(), pad );
094 writeTypeCategories( writer, type.getCategoryDescriptors(), pad );
095 writeTypeState( writer, type.getStateGraph(), pad );
096 }
097
098 private void writeTypeInfo( Writer writer, InfoDescriptor info, String pad ) throws IOException
099 {
100 writer.write( "\n" + pad + "<info" );
101 writer.write( " name=\"" + info.getName() );
102 writer.write( "\"\n" + pad + " class=\"" + info.getClassname() );
103 writer.write( "\"\n" + pad + " version=\"" + info.getVersion() );
104 writer.write( "\"\n" + pad + " lifestyle=\"" + info.getLifestylePolicy().getName().toLowerCase() );
105 writer.write( "\"\n" + pad + " collection=\"" + info.getCollectionPolicy().getName().toLowerCase() );
106 writer.write( "\"\n" + pad + " threadsafe=\"" + info.getThreadSafePolicy().getName().toLowerCase() );
107 writer.write( "\"" );
108 if( info.getAttributeNames().length > 0 )
109 {
110 writer.write( ">" );
111 writeAttributes( writer, info, pad + " " );
112 writer.write( "\n" + pad + "</info>" );
113 }
114 else
115 {
116 writer.write( "/>" );
117 }
118 }
119
120 private void writeTypeServices( Writer writer, ServiceDescriptor[] services, String pad ) throws IOException
121 {
122 if( services.length == 0 )
123 {
124 return;
125 }
126 else
127 {
128 writer.write( "\n" + pad + "<services>" );
129 for( int i=0; i<services.length; i++ )
130 {
131 ServiceDescriptor service = services[i];
132 writer.write( "\n" + pad + " <service" );
133 writer.write( " class=\"" + service.getClassname() );
134 writer.write( "\" version=\"" + service.getVersion() );
135 writer.write( "\"/>" );
136 }
137 writer.write( "\n" + pad + "</services>" );
138 }
139 }
140
141 private void writeTypeContext( Writer writer, ContextDescriptor context, String pad ) throws IOException
142 {
143 EntryDescriptor[] entries = context.getEntryDescriptors();
144 if( entries.length > 0 )
145 {
146 writer.write( "\n" + pad + "<context>" );
147 for( int i=0; i<entries.length; i++ )
148 {
149 EntryDescriptor entry = entries[i];
150 writer.write( "\n" + pad + " <entry" );
151 writer.write( " key=\"" + entry.getKey() );
152 writer.write( "\" class=\"" + entry.getClassname() );
153 if( entry.isOptional() )
154 {
155 writer.write( "\" optional=\"true\"" );
156 }
157 else
158 {
159 writer.write( "\" optional=\"false\"" );
160 }
161 if( entry.isVolatile() )
162 {
163 writer.write( "\" volatile=\"true\"" );
164 }
165 writer.write( "/>" );
166 }
167 writer.write( "\n" + pad + "</context>" );
168 }
169 else
170 {
171 return;
172 }
173 }
174
175 private void writeTypeCategories(
176 Writer writer, CategoryDescriptor[] categories, String pad ) throws IOException
177 {
178 if( categories.length > 0 )
179 {
180 writer.write( "\n" + pad + "<categories>" );
181 for( int i=0; i<categories.length; i++ )
182 {
183 CategoryDescriptor category = categories[i];
184 writer.write( "\n" + pad + " <category" );
185 writer.write( " name=\"" + category.getName() );
186 writer.write(
187 "\" priority=\""
188 + category.getDefaultPriority().getName().toLowerCase() );
189 writer.write( "\"" );
190
191 if( category.getAttributeNames().length > 0 )
192 {
193 writer.write( ">" );
194 writeAttributes( writer, category, pad + " " );
195 writer.write( "\n" + pad + " </category>" );
196 }
197 else
198 {
199 writer.write( "/>" );
200 }
201 }
202 writer.write( "\n" + pad + "</categories>" );
203 }
204 else
205 {
206 return;
207 }
208 }
209
210 private void writeTypeState( Writer writer, State state, String pad ) throws IOException
211 {
212 STATE_GRAPH_ENCODER.writeState( writer, state, pad );
213 writer.write( "\n" );
214 }
215
216 private void writeAttributes( Writer writer, Descriptor descriptor, String pad ) throws IOException
217 {
218 String[] names = descriptor.getAttributeNames();
219 for( int i=0; i<names.length; i++ )
220 {
221 String name = names[i];
222 String value = descriptor.getAttribute( name, "" );
223 writer.write( "\n" + pad + "<property" );
224 writer.write( " name=\"" + name );
225 writer.write( "\" value=\"" + value );
226 writer.write( "\"/>" );
227 }
228 }
229 }
230